package xin.nick.roc.consumer.proxy;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import xin.nick.roc.consumer.client.ProviderInfo;
import xin.nick.roc.consumer.client.RpcClient;
import xin.nick.rpc.common.RpcRequest;
import xin.nick.rpc.common.RpcResponse;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Objects;
import java.util.UUID;

/**
 * @author Nick
 * @date 2021/7/4
 * @description
 */
@Slf4j
public class RpcClientProxy {

    public static Object createProxy(Class serviceClass) {

        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{serviceClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 封装request请求对象
                RpcRequest rpcRequest = new RpcRequest();
                rpcRequest.setRequestId(UUID.randomUUID().toString());
                rpcRequest.setClassName(method.getDeclaringClass().getName());
                rpcRequest.setMethodName(method.getName());
                rpcRequest.setParameterTypes(method.getParameterTypes());
                rpcRequest.setParameters(args);
                // 创建RpcClient对象
                ProviderInfo providerInfo = ProviderInfo.getProviderInfo();
                log.info("调用rpc服务器: {}:{}",providerInfo.getIp(), providerInfo.getPort());
                RpcClient rpcClient = new RpcClient(providerInfo.getIp(), providerInfo.getPort());

                try {
                    // 发送请求
                    Object responseMsg = rpcClient.send(JSON.toJSONString(rpcRequest));
                    RpcResponse rpcResponse = JSON.parseObject(responseMsg.toString(), RpcResponse.class);
                    if(Objects.nonNull(rpcResponse.getError())) {
                        throw new RuntimeException(rpcResponse.getError());
                    }
                    // 返回结果
                    Object result = rpcResponse.getResult();
                    return JSON.parseObject(result.toString(), method.getReturnType());
                } catch (Exception e) {
                    throw e;
                } finally {
                    rpcClient.close();
                }

            }
        });

    }

}
